package org.BUPT.api.controller;


import lombok.extern.log4j.Log4j2;
import org.BUPT.application.service.MessageService;
import org.BUPT.domain.model.message.*;
import org.BUPT.application.service.QuestionService;
import org.BUPT.infrastructure.exception.NullObjectException;
import org.BUPT.domain.service.impl.QuestionServiceImpl;
import org.BUPT.domain.model.question.*;
import org.BUPT.infrastructure.exception.PersistException;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.Date;
import java.util.List;


// todo: 用户查看自己提问过的问题(已实现)
// todo: 用户查看自己关注的问题(已实现)
// todo: 添加用户关注问题的关联(已实现)
// todo: 添加用户给回答点赞的关联(已实现）
// 每个接口都已接受过一遍测试


@RestController
@Log4j2
@CrossOrigin
public class QuestionServiceController {
    @Autowired
    QuestionService questionService;

    @Autowired
    MessageService messageService;

    /**
     * GET
     * 获取一页问题的缩略信息，每页包含7道问题（可以修改）
     * 修改每页包含的问题数，详见
     * @see QuestionServiceImpl#getPage(int)
     * 关于问题缩略信息中包含的内容，详见
     * @see QuestionBO#view()
     * @param pageId: 所获取的页面号
     * @return 该页问题缩略信息 {@code QuestionBO.view()}列表
     **/
    @GetMapping("/page/{pageId}")
    public List<QuestionBO> getPage(@PathVariable int pageId){
        // 注意这里返回的QuestionBO是问题的缩略信息，不可持久化
        try{
            return questionService.getQuestionPage(pageId);
        }
        catch (Exception e){
            // 日志记录操作中可能出现的错误，下同
            log.info(e.getMessage());
            return null;
        }
    }


    /**
     * GET
     * 获取一个问题的详细信息，包括其提出者信息，对于其的所有回答信息（回答信息中包括评论信息）等等
     * 详细信息的内容详见
     * @see QuestionBO
     * @param id: 需要查询的问题编号
     * @return 该问题的详细信息 {@code QuestionBO}
     */
    @GetMapping("/question/{id}")
    QuestionBO getQuestion(@PathVariable int id){
        try {
            return questionService.getQuestion(id);
        }
        catch (Exception e){
            log.info(e.getMessage());
            return null;
        }
    }

    /**
     * GET
     * 获取一个用户关注的所有问题的缩略信息的列表
     * 关于问题缩略信息中包含的内容，详见
     * @see QuestionBO#view()
     * @param userId: 需要查询的用户编号
     * @return 该用户所关注的问题缩略信息 {@code QuestionBO.view()}列表
     */
    @GetMapping("/getSubscribedQuestion/{userId}")
    List<QuestionBO> getSubscribedQuestionList(@PathVariable int userId){
        try{
        return questionService.getSubscribedQuestion(userId);
        }
        catch(Exception e){
            log.info(e.getMessage());
            return null;
        }
    }

    /**
     * GET
     * 获取一个用户问过的所有问题的缩略信息的列表
     * 关于问题缩略信息中包含的内容，详见
     * @see QuestionBO#view()
     * @param userId: 需要查询的用户编号
     * @return 该用户所问过的问题的缩略信息 {@code QuestionBO.view()}列表
     */
    @GetMapping("/getAskedQuestion/{userId}")
    List<QuestionBO> getAskedQuestionList(@PathVariable int userId){
        try{
            return questionService.getAskedQuestion(userId);
        }
        catch(Exception e){
            log.info(e.getMessage());
            return null;
        }
    }

    /**
     * POST
     * 用户提出一个问题
     * @param title: 问题的题目（简述）
     * @param userId: 提问者id
     * @param content: 问题的内容
     * @param subjectId: 问题相关的课程Id（每个问题对应且只对应一个特定课程）
     * @param tags: 问题相关的知识点（每个问题可以有多个知识点）
     * @param teacherId: 邀请的老师
     * @return 若问题提出成功，则返回空字符串，若失败，则返回失败信息
     */
    @PostMapping("/addQuestion")
    public String addQuestion(
            @RequestParam(value="title") String title,
            @RequestParam(value = "userId") int userId,
            @RequestParam(value = "content") String content,
            @RequestParam(value = "subjectId") int subjectId,
            @RequestParam(value = "tags") String[] tags,
            @RequestParam(value = "teacherId") int teacherId
    ){
        try {

            QuestionBO questionBO = questionService.createQuestion(title,userId,content,subjectId,tags);
            questionBO.save();
            messageService.addMessage(new UserInvited(
                    questionBO.getId(),
                    userId,
                    teacherId
            ));
            return "";
        }
        catch (Exception e){
            log.info(e.getMessage());
            return e.getMessage();
        }
    }

    // todo:用户问问题时@某个老师并产生消息

    /**
     * POST
     * 用户修改一个问题
     * @param id: 问题修改者的id
     * @param title: 修改后问题的题目（简述）
     * @param content: 修改后问题的内容
     * @param subjectId: 修改后问题的学科Id
     * @param tags: 修改后问题的知识点
     * @return 若问题修改成功，则返回空字符串，若失败，则返回失败信息
     */
    @PostMapping("/modifyQuestion")
    public String modifyQuestion(
            @RequestParam(value="questionId") int id,
            @RequestParam(value="title") String title,
            @RequestParam(value = "content") String content,
            @RequestParam(value = "subjectintId")  int subjectId,
            @RequestParam(value = "tags") String[] tags
    ){
        try{
            QuestionBO questionBO = questionService.getQuestion(id);
            List<Integer> subscribedUsers = questionBO.getSubscribedUsers();
            List<AnswerBO> askedUsers = questionBO.getAnswers();
            for (int i :subscribedUsers){
                messageService.addMessage(
                        new SubscribedQuestionUpdated(
                                id,
                                questionBO.getUserId(),
                                i
                        )
                );
            }
            for (AnswerBO answerBO:askedUsers){
                messageService.addMessage(
                        new AnsweredQuestionUpdated(
                                id,
                                questionBO.getUserId(),
                                answerBO.getUserId()
                        )
                );
            }
            questionBO.
                    setTitle(title)
                    .setContent(content)
                    .setSubjectId(subjectId)
                    .setEditTime(new Date())
                    .setTags(Arrays.asList(tags)).save();
            return "";
        }
        catch (NullObjectException | PersistException e){
            log.info(e.getMessage());
            return e.getMessage();
        }
    }



    /**
     * POST
     * 用户关注一个问题
     * @param userId: 此用户的id
     * @param questionId: 所关注问题的id
     * @return 若问题关注成功，则返回空字符串，若失败，则返回失败信息
     */
    @PostMapping("/subscribeQuestion")
    public String subscribeQuestion(
            @RequestParam(value = "userId") int userId,
            @RequestParam(value = "questionId") int questionId
    ){
        try
        {

            int destUserId = questionService.getQuestion(questionId).getUserId();
            messageService.addMessage(
                    new QuestionSubscribed(
                    questionId,
                    userId,
                    destUserId));
            questionService.subscribeQuestion(userId, questionId);
            return "";
        }
        catch (Exception e) {
            log.info(e.getMessage());
            return e.getMessage();
        }
    }

    /**
     * POST
     * 用户取消关注一个问题
     * @param userId: 此用户的id
     * @param questionId: 所关注问题的id
     * @return 若问题取消关注成功，则返回空字符串，若失败，则返回失败信息
     */
    @PostMapping("/unsubscribeQuestion")
    public String unsubscribeQuestion(
            @RequestParam(value = "userId") int userId,
            @RequestParam(value = "questionId") int questionId
    ){
        try
        {
            questionService.unsubscribeQuestion(userId, questionId);
            return "";
        }
        catch (Exception e) {
            log.info(e.getMessage());
            return e.getMessage();
        }
    }







}
